﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.ComponentModel;

namespace RSCore.Helper.WPF.Data
{
	public class Property : Item, IDisposable
	{
		#region Fields

		private object _instance;
		private PropertyDescriptor _property;

		#endregion

		#region Initialization

		public Property(object instance, PropertyDescriptor property)
		{
			this._instance = instance;
			this._property = property;

			this._property.AddValueChanged(_instance, instance_PropertyChanged);
		}

		#endregion

		#region Properties

		/// <value>
		/// Initializes the reflected instance property
		/// </value>
		/// <exception cref="NotSupportedException">
		/// The conversion cannot be performed
		/// </exception>
		public object Value
		{
			get { return _property.GetValue(_instance); }
			set
			{
				object currentValue = _property.GetValue(_instance);
				if (value != null && value.Equals(currentValue))
				{
					return;
				}
				Type propertyType = _property.PropertyType;
				if (propertyType == typeof(object) ||
					value == null && propertyType.IsClass ||
					value != null && propertyType.IsAssignableFrom(value.GetType()))
				{
					_property.SetValue(_instance, value);
				}
				else
				{
					TypeConverter converter = TypeDescriptor.GetConverter(_property.PropertyType);
					object convertedValue = converter.ConvertFrom(value);
					_property.SetValue(_instance, convertedValue);
				}				
			}
		}

		public string Name
		{
			get { return _property.Name; }
		}

		public bool IsWriteable
		{
			get { return !IsReadOnly; }
		}

		public bool IsReadOnly
		{
			get { return _property.IsReadOnly; }
		}

		public Type PropertyType
		{
			get { return _property.PropertyType; }
		}

		public string Category
		{
			get { return _property.Category; }
		}
		
		#endregion

		#region Event Handlers

		void instance_PropertyChanged(object sender, EventArgs e)
		{
			NotifyPropertyChanged("Value");
		}
		
		#endregion		

		#region IDisposable Members

		protected override void Dispose(bool disposing)
		{
			if (Disposed)
			{
				return;
			}
			if (disposing)
			{
				_property.RemoveValueChanged(_instance, instance_PropertyChanged);
			}
			base.Dispose(disposing);
		}

		#endregion
	}
}
